package com.gitee.wsl

import com.gitee.wsl.concurrent.collections.ConcurrentMutableList
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.withTimeout
import kotlin.time.Duration

open class TestBase {
}

// this should live in some matchers class, but can't inline in an interface :(
inline fun <reified T> shouldThrow(thunk: () -> Any?): T {
    val e = try {
        thunk()
        null
    } catch (e: Throwable) {
        e
    }

    val exceptionClassName = T::class.simpleName

    if (e == null)
        throw AssertionError("Expected exception ${T::class.simpleName} but no exception was thrown")
    else if (e::class.simpleName != exceptionClassName)
        throw AssertionError("Expected exception ${T::class.simpleName} but ${e::class.simpleName} was thrown")
    else
        return e as T
}



/**
 * Returns a list of flow items captured for [duration]
 * @param duration of capturing
 * @return a list of flow items captured for [duration]
 */
suspend fun <T> Flow<T>.captureFor(duration: Duration): List<T> {
    val output = ConcurrentMutableList<T>()

    try {
        withTimeout(duration) {
            collect { output += it }
        }
    } catch (e: TimeoutCancellationException) {
        // ignore
    }
    return output
}